package com.zed.games.answer.show;

import cn.hutool.core.io.IoUtil;
import com.zed.api.common.Registration;
import com.zed.api.games.GameException;
import com.zed.api.games.answer.NotSupportProtocolException;
import com.zed.api.games.answer.show.AlternativeAnswer;
import com.zed.api.games.answer.show.AnswerShowWorld;

import java.io.InputStream;
import java.io.Serial;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * {@link java.net.URL},基于URL的展示题目
 *
 * @author Zed
 */
public class URLAnswerShowWorld extends AnswerShowWorld implements Registration {
    @Serial
    private static final long serialVersionUID = 6121382867552826390L;

    /**
     * 对文件的缓存
     */
    private static final Map<URL, byte[]> CACHE = new ConcurrentHashMap<>();

    private URL url;

    public URLAnswerShowWorld(Builder builder) throws Exception {
        super(builder);
        String url = Objects.requireNonNull(builder.url, "\"url\" cannot be null.");
        this.url = new URL(url);
    }

    /**
     * 急切的初始化
     */
    protected void fetchBytes() throws GameException {
        String protocol = this.url.getProtocol();
        if (protocol.equalsIgnoreCase("http") || protocol.equalsIgnoreCase("https")) {
            boolean b = CACHE.containsKey(this.url);
            if (!b) {
                InputStream ip = null;
                try {
                    URLConnection urlConnection = url.openConnection();
                    urlConnection.setConnectTimeout(100000);
                    int contentLength = urlConnection.getContentLength();
                    if (contentLength > 5242880) throw new GameException("请上传文件小于5MB的.");
                    ip = urlConnection.getInputStream();
                    byte[] bytes = IoUtil.readBytes(ip);
                    CACHE.put(this.url, bytes);
                } catch (Throwable e) {
                    throw new GameException(e);
                } finally {
                    IoUtil.close(ip);
                }
            }
            return;
        }
        throw new NotSupportProtocolException("暂不支持".concat(protocol).concat("协议"));
    }

    /**
     * 创建构建器
     *
     * @return {@link Builder}
     */
    public static Builder newBuilder() {
        return new Builder();
    }

    @Override
    public Object getTheme() throws GameException {
        this.fetchBytes();
        byte[] bytes = CACHE.get(this.url);
        return bytes;
    }

    @Override
    public boolean unregister() {
        return CACHE.remove(this.url) != null;
    }

    public static class Builder extends AnswerShowWorld.Builder {

        private String url;

        /**
         * 设置{@link String}
         *
         * @param url {@link String}
         * @return {@link Builder}
         */
        public Builder url(String url) {
            this.url = url;
            return this;
        }

        @Override
        public Builder id(String id) {
            super.id(id);
            return this;
        }

        @Override
        public Builder addAlternativeAnswer(AlternativeAnswer alternativeAnswer) {
            super.addAlternativeAnswer(alternativeAnswer);
            return this;
        }

        @Override
        public Builder addTips(String tip) {
            super.addTips(tip);
            return this;
        }

        @Override
        public Builder removeTips(String tip) {
            super.removeTips(tip);
            return this;
        }

        @Override
        public AnswerShowWorld build() throws Exception {
            return new URLAnswerShowWorld(this);
        }
    }
}
